package com.gitee.deament.server.core.cli.db.list;

import cn.hutool.core.util.NumberUtil;
import com.gitee.deament.server.config.SystemConfig;
import com.gitee.deament.server.core.annotation.CliHander;
import com.gitee.deament.server.core.cli.AbstractCli;
import com.gitee.deament.server.core.data.ConnectData;
import com.gitee.deament.server.core.data.DBData;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

import java.util.List;

/**
 * LREM key count value
 * 可用版本： >= 1.0.0
 * 时间复杂度： O(N)， N 为列表的长度。
 * 根据参数 count 的值，移除列表中与参数 value 相等的元素。
 * <p>
 * count 的值可以是以下几种：
 * <p>
 * count > 0 : 从表头开始向表尾搜索，移除与 value 相等的元素，数量为 count 。
 * <p>
 * count < 0 : 从表尾开始向表头搜索，移除与 value 相等的元素，数量为 count 的绝对值。
 * <p>
 * count = 0 : 移除表中所有与 value 相等的值。
 * <p>
 * 返回值
 * 被移除元素的数量。 因为不存在的 key 被视作空表(empty list)，所以当 key 不存在时， LREM 命令总是返回 0 。
 *
 * @author deament
 */
@CliHander(command = "LREM")
public class LREMcli extends AbstractCli {
    @Override
    public void executeCli(ChannelHandlerContext channelHandlerContext, String command) {
        List<String> cliValues = getValues(command);
        if (cliValues.size() != 4) {
            channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame("ERR wrong number of arguments for 'LREM' command"));
            return;
        }
        int db = ConnectData.SELECT_DB_STORAGE.getUseDB(channelHandlerContext.channel().id().asLongText());
        DBData dbData = SystemConfig.dbData;
        String listKey = cliValues.get(1);
        String listCount = cliValues.get(2);
        String removeValue = cliValues.get(3);
        if (!NumberUtil.isInteger(listCount)) {
            channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame("第三个参数不是数字"));
        }
        if(Integer.parseInt(listCount)==0){
            removeValueEqualsZero(channelHandlerContext,db, listKey,removeValue);
        }
        if(Integer.parseInt(listCount)>0){
            removeValueLargeZero(channelHandlerContext,db, listKey,removeValue,Integer.parseInt(listCount));
        }
        if(Integer.parseInt(listCount)<0){
            removeValueLessZero(channelHandlerContext,db, listKey,removeValue,Integer.parseInt(listCount));
        }

    }

    /**
     * count = 0 : 移除表中所有与 value 相等的值。
     */
    private void removeValueEqualsZero(ChannelHandlerContext channelHandlerContext, int db, String key, String valueStr) {
            int removecount=0;
        try {
            List<String> value = SystemConfig.dbData.getList(db, key).getValue();
            while (value.contains(valueStr)) {
                int index = value.indexOf(valueStr);
                if(index>-1){
                    value.remove(index);
                    removecount++;
                }

            }
            channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame(removecount+""));
        } catch (Exception e) {
            channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame(e.getMessage()));
        }
    }

    /**
     * count < 0 : 从表尾开始向表头搜索，移除与 value 相等的元素，数量为 count 的绝对值。
     */
    private void removeValueLessZero(ChannelHandlerContext channelHandlerContext, int db, String key, String valueStr, Integer count) {
        int removecount=0;
        try {
            List<String> value = SystemConfig.dbData.getList(db, key).getValue();
            int absCount = Math.abs(count);
            while (value.contains(valueStr) && absCount > 0) {
                int index = value.lastIndexOf(valueStr);
                if(index>-1){
                    removecount++;
                    value.remove(index);
                }
                absCount--;
            }
            channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame(removecount+""));
        } catch (Exception e) {
            channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame(e.getMessage()));
        }
    }
    /**
     * count > 0 : 从表头开始向表尾搜索，移除与 value 相等的元素，数量为 count 。
     */
    private void removeValueLargeZero(ChannelHandlerContext channelHandlerContext, int db, String key, String valueStr, Integer count) {
        int removecount=0;
        try {
            List<String> value = SystemConfig.dbData.getList(db, key).getValue();
            int absCount = Math.abs(count);
            while (value.contains(valueStr) && absCount > 0) {
                int index = value.indexOf(valueStr);
                if(index>-1){
                    removecount++;
                    value.remove(index);
                }
                absCount--;
            }
            channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame(removecount+""));
        } catch (Exception e) {
            channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame(e.getMessage()));
        }
    }

}
